#include "Data.h"

#define PARALLEL 0
#define NUM_NODES 1


int main(int argc, char **argv)
{
    FILE *arq, *arq_palavras, *arq_frases;
    long int tamanho_arq;
    char *particao_texto, separador[12];
    register int i = 0, j = 0;
    int byte_inicio = 0, byte_fim = 0, flag_arquivo = 0;

    /* Variáveis partição */
    long int particao_tamanho = 0, part_offset_inic=0, part_offset_fim=0;        
	short int num_threads = 1; /* Quantos threads serão criadas para verificar as partições */
    char *str_subpart;

	/* Inicializa a struct de primos para o cálculo do algoritmo de crivo */
    primos *list;
    list = (primos *) malloc(sizeof(primos));
	
	list->prime_list = (int *) malloc ((MAXLENGTH)*sizeof(int));
	list->last_index = 0;
	list->last_prime = 2;
	list->max_len = MAXLENGTH;
	list->prime_list[0] = 2;


	/* Seleciona arquivo pequeno */
	flag_arquivo = ARQUIVO_PEQUENO;
	char nome[20] = "shakespe.txt";   


    /* Definição dos separadores */
    separador[0] = '\n';
    separador[1] = '\r';
    separador[2] = '\t';
    separador[3] = '.';
    separador[4] = '!';
    separador[5] = '?';
    separador[6] = '-';
    separador[7] = '\'';
    separador[8] = '\0';

	/* Considera apenas palavras para o arquivo grande    */
	/* Considera palavras e frases para o arquivo pequeno */
    if (flag_arquivo == ARQUIVO_GRANDE)
    {
            separador[8]=' ';
    }
    separador[9]='\0';

	/* Abre o arquivo onde serao armazenados os palíndromos de palavras */
	arq_palavras = fopen ("Palindromos_palavras.txt","w");

	/* Abre o arquivo onde serao armazenados os palíndromos de frases */
	arq_frases = fopen ("Palindromos_frases.txt","w");
    
	/* Abre o arquivo de texto e verifica se existe */        
	arq = fopen(nome,"r+"); 
    if (arq == NULL) 
            return EXIT_FAILURE;

    /* Calcula tamanho do arquivo com ftell() */
    fseek(arq,0,SEEK_END);
    tamanho_arq = ftell(arq);

	/*===============================================================================*/
    
    /* 	Sequencialmente, o arquivo grande será dividido em apenas uma partição, ou seja,  */
	/*	todo o arquivo texto será armazenado em apenas uma string, em seguida é realizado */
	/*	a verificação de palíndromos. Por isso, o número de nós e threads utilizados são  */
	/*	definidos em um.						 							  		      */

	/*===============================================================================*/

    /* Calcula o byte de início da partição, percorre FILE até achar um separador */
    byte_inicio = (int)(tamanho_arq*((float)i/(float)NUM_NODES)); 
    byte_inicio = busca_UltimoSeparador(arq, byte_inicio, separador);

    /* Calcula o byte final da partição, percorre FILE até achar um separador ou EOF */
    byte_fim = (int)(tamanho_arq*((float)(i+1)/(float)NUM_NODES));
    byte_fim = busca_UltimoSeparador(arq, byte_fim, separador);

    /* Transfere a partição para uma string */
    cria_Particao(arq, &particao_texto, byte_inicio, byte_fim);
    
    /* O mesmo que strlen() */
	particao_tamanho = byte_fim-byte_inicio;
        

	/* Apenas uma thread por ser uma execução sequencial */
    num_threads = 1;
	
	printf("Encontrando palindromos...\n");
	
    for(j=0; j<num_threads; j++)
    {		
		/* Particiona a string de acordo com o número de processadores */
		/* Offset inicial da string de acordo com a thread */
        part_offset_inic = (int)(particao_tamanho * ((float)j/(float)num_threads));
        part_offset_inic =      busca_UltimoSeparadorString(particao_texto, part_offset_inic, separador);

		/* Offset final da string de acordo com a thread*/
        part_offset_fim = (int)(particao_tamanho * ((float)(j+1)/(float)num_threads));
        part_offset_fim =       busca_UltimoSeparadorString(particao_texto, part_offset_fim, separador);
        

        /* Utiliza os offsets para armazenar a nova substring em uma outra string */        
        str_subpart = (char *) malloc((part_offset_fim-part_offset_inic+1)*sizeof(char));
        strncpy(str_subpart,&(particao_texto[part_offset_inic]), part_offset_fim-part_offset_inic);
        str_subpart[part_offset_fim-part_offset_inic] = '\0';


        /* Verifica os palíndromos e primos da subpartição */
        if(flag_arquivo == ARQUIVO_PEQUENO)
        {                
			imprimePalindromos_Palavra(str_subpart, separador, list, arq_palavras, PARALLEL);
            imprimePalindromos_Frase(str_subpart, separador, list, arq_frases, PARALLEL);
        }
        else
            imprimePalindromos_Palavra(str_subpart, separador, list, arq_palavras, PARALLEL);
        

		/* Libera a memória da subparticao */
        free(str_subpart); 
    }

	printf("Palindromos encontrados!\n");

	/* Libera a memória da partição */
    free(particao_texto); 
	
    free(list->prime_list);
    free(list);

	/* Fecha arquivos */
	fclose(arq_palavras);
	fclose(arq_frases);
	
	/* Fecha o ponteiro do arquivo */        
    if (!fclose(arq))  
    	return EXIT_FAILURE;

    return EXIT_SUCCESS;
}
